Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hardhat 3 Migration
Migrates eth/ from Hardhat 2 to Hardhat 3. All 159 tests pass.
What changed
Runtime model
"type": "module" — the package is now pure ESM. All imports use import/export; no require().
defineConfig() replaces the plain config object export. Plugins are declared in the plugins: [] array instead of side-effect imports.
configVariable() replaces vars.get() for secret management. Values are lazily resolved — only accessed when the target network is actually used, so npm test works without any keystore entries set.
hre.network.getOrCreate() replaces direct ethers/hre.ethers access. Each call returns a typed connection object carrying ethers, viem, networkHelpers, and networkName. Scripts use getOrCreate() without arguments so the --network CLI flag is respected in production; tests use the same call, which resolves to Hardhat 3's built-in "default" in-process network.
Test runner
node:test replaces Mocha. describe, it, before, afterEach are imported from "node:test".
Functional tests use viem assertions (revertWith, revertWithCustomError). Deployment tests use hardhat-ethers-chai-matchers for ethers-based contracts.
Toolchain
hardhat@3, hardhat-toolbox-viem@5, @nomicfoundation/hardhat-ethers@4, @nomicfoundation/hardhat-ethers-chai-matchers@3
@openzeppelin/hardhat-upgrades@4.0.0-alpha.0 (exact pin — no caret, first H3-compatible release)
@solidstate/hardhat-abi-exporter@3 replaces hardhat-abi-exporter (H3 incompatible)
@openzeppelin/contracts and contracts-upgradeable pinned to ~5.4.0 — OZ 5.5 removed ReentrancyGuardUpgradeable used by SupportV2
Contracts
contracts/ERC1967Proxy.sol — thin wrapper exposing OZ's ERC1967Proxy as a named project artifact, needed because OZ v5 no longer registers it for deployContract in tests.
Type safety
upgradesApi typed as HardhatUpgrades (exported by OZ) instead of any
Viem wallet/public client fields typed as WalletClient/PublicClient; contract instance fields carry targeted eslint-disable with an explanation (viem's GetContractReturnType requires compile-time ABI)
catch (error: unknown) with explicit (error as Error) cast replaces catch (error: any)
Notable H3 behaviour
hre.network.getOrCreate() without arguments resolves to network name "default" (Hardhat 3's hardcoded DEFAULT_NETWORK_NAME), regardless of defaultNetwork: "hardhat" in the config. That config setting only affects CLI defaults for npx hardhat run. Deployment files written during tests are therefore named -default-; the test cleanup functions and assertions reflect this.
The validate-contract.ts script is imported transitively by deploy scripts, which are imported by deployment test files. A top-level main() call in that module would fire during test loading. It is guarded with if (!process.env.HH_TEST) — the environment variable set by Hardhat 3's test runner at startup.